---
title: 责任链模式
description: Chain of Responsibility Pattern - 为请求创建了一个接收者对象的链
sidebar_position: 1
---


## 定义
**职责链模式（chain of responsibility pattern）：将请求的发送和接受解耦，避免将一个请求的发送者与接收者耦合在一起，让多个接受对象都有机会处理请求，将接受请求的对象连接成一条链，并且沿着这条链传递请求，直到有一个对象能够处理它为止。**

在职责链模式中，多个处理器（也就是上面提到的“接受对象”）依次处理同一个请求。一个请求先经过 A 处理器，然后再把请求传递给 B 处理器，B 处理器处理完再传递给 C 处理器，以此类推，形成一个链条。链条上的每个处理器各自承担各自的处理职责，所以叫做职责链模式。

![](https://wkq-img.oss-cn-chengdu.aliyuncs.com/site/20250823171010.png)

在 GoF 的定义中，一旦某个处理器能处理这个请求，就不会继续将请求传递给后续的处理器了。 当然，在实际的开发中，也存在对这个模式的变体，那就是请求不会中途终止，而是会被所有的处理器都处理一遍。

职责链模式有两种常用的实现，一种是使用链表来存储处理器，另一种是使用数组来存储处理器，后面一种实现方式更加简单。
## 模式原理

![](https://wkq-img.oss-cn-chengdu.aliyuncs.com/site/20250913160954.png)
```java title='抽象的处理者类'

/**
 * 抽象处理者角色
 */
public abstract class Handler {
  protected Handler successor = null;
  public void setSuccessor(Handler successor) {
    this.successor = successor;
  }
  public final void handle(){
    boolean handled = doHandle();
    if (successor!=null&&!handled){
      successor.handle();
    }
  };
  protected abstract boolean doHandle();
}


```
```java title='具体的处理者类A'

public class HandlerA extends Handler {


  @Override
  protected boolean doHandle() {
    System.out.println("HandlerA.doHandle");
    return false;
  }
}


```
```java title='具体的处理者类B'
public class HandlerB extends Handler {

  @Override
  protected boolean doHandle() {
    System.out.println("HandlerB.doHandle");
    return false;
  }
}

```
```java title='具体的处理者类C'
public class HandlerC extends Handler {

  @Override
  protected boolean doHandle() {
    System.out.println("HandlerC.doHandle");
    return false;
  }
}


```

```java title='HandleChain'
package com.e6yun.project.behavior.chainofresponsibility.example5;

public class HandlerChain {
  private Handler head= null;
  private Handler tail= null;
  public void addHandler(Handler handler){
    handler.setSuccessor(null); // 链尾
    if (head == null) { // 链头
      head = handler;
      tail = handler;
      return;
    }
    // 其余情况，在原本的链尾添加元素
    tail.setSuccessor(handler);
    tail = handler; // 修改链尾指针
  }
  public void handle(){
    if (head!=null){
      head.handle();
    }
  }
}


```

```java title='客户端'
public class Client {

  public static void main(String[] args) {
    HandlerChain chain = new HandlerChain();
    chain.addHandler(new HandlerA());
    chain.addHandler(new HandlerB());
    chain.addHandler(new HandlerC());
    chain.handle();
  }
}
```
在 GoF 给出的定义中，如果处理器链上的某个处理器能够处理这个请求，那就不会继续往下传递请求。实际上，职责链模式还有一个变体，那就是请求会被所有的处理器都处理一遍，不存在中途终止的情况。
```java title='所有处理器都处理'
public abstract class Handler {
  protected Handler successor = null;

  public void setSuccessor(Handler successor) {
    this.successor = successor;
  }

  public final void handle() {
    doHandle();
    if (successor != null) {
      successor.handle();
    }
  }

  protected abstract void doHandle();
}

public class HandlerA extends Handler {
  @Override
  protected void doHandle() {
    //...
  }
}

public class HandlerB extends Handler {
  @Override
  protected void doHandle() {
    //...
  }
}

public class HandlerChain {
  private Handler head = null;
  private Handler tail = null;

  public void addHandler(Handler handler) {
    handler.setSuccessor(null);

    if (head == null) {
      head = handler;
      tail = handler;
      return;
    }

    tail.setSuccessor(handler);
    tail = handler;
  }

  public void handle() {
    if (head != null) {
      head.handle();
    }
  }
}

// 使用举例
public class Application {
  public static void main(String[] args) {
    HandlerChain chain = new HandlerChain();
    chain.addHandler(new HandlerA());
    chain.addHandler(new HandlerB());
    chain.handle();
  }
}
```

## 应用实例
使用职责链模式实现审批流，审批的过程会有不同级别的负责人加入进行审批（支持一级或者二级、三级审核人参与审核）。


![](https://wkq-img.oss-cn-chengdu.aliyuncs.com/site/20250823204029.png)
### 不使用设计模式

```java title='不使用设计模式的审批流程'
public class AuthService {
    
    public void auth(String userId, String orderId) {
        // 模拟从数据库获取用户信息
        String userLevel = getUserLevel(userId);
        
        if ("3".equals(userLevel)) {
            System.out.println("3级审批负责人处理：" + orderId);
            // 3级审批逻辑
            if (Math.random() > 0.5) {
                System.out.println("3级审批通过");
                // 继续2级审批
                if ("2".equals(getUserLevel("level2_user"))) {
                    System.out.println("2级审批负责人处理：" + orderId);
                    if (Math.random() > 0.5) {
                        System.out.println("2级审批通过");
                        // 继续1级审批
                        if ("1".equals(getUserLevel("level1_user"))) {
                            System.out.println("1级审批负责人处理：" + orderId);
                            if (Math.random() > 0.5) {
                                System.out.println("1级审批通过");
                                System.out.println("审批流程完成");
                            } else {
                                System.out.println("1级审批拒绝");
                            }
                        }
                    } else {
                        System.out.println("2级审批拒绝");
                    }
                }
            } else {
                System.out.println("3级审批拒绝");
            }
        } else if ("2".equals(userLevel)) {
            System.out.println("2级审批负责人处理：" + orderId);
            if (Math.random() > 0.5) {
                System.out.println("2级审批通过");
                // 继续1级审批
                if ("1".equals(getUserLevel("level1_user"))) {
                    System.out.println("1级审批负责人处理：" + orderId);
                    if (Math.random() > 0.5) {
                        System.out.println("1级审批通过");
                        System.out.println("审批流程完成");
                    } else {
                        System.out.println("1级审批拒绝");
                    }
                }
            } else {
                System.out.println("2级审批拒绝");
            }
        } else if ("1".equals(userLevel)) {
            System.out.println("1级审批负责人处理：" + orderId);
            if (Math.random() > 0.5) {
                System.out.println("1级审批通过");
                System.out.println("审批流程完成");
            } else {
                System.out.println("1级审批拒绝");
            }
        }
    }
    
    private String getUserLevel(String userId) {
        // 模拟从数据库获取用户级别
        if ("level3_user".equals(userId)) return "3";
        if ("level2_user".equals(userId)) return "2";
        if ("level1_user".equals(userId)) return "1";
        return "3"; // 默认3级
    }
}
```

**问题分析：**
- 代码中存在大量的 if-else 嵌套
- 审批逻辑硬编码，难以扩展
- 违反了开闭原则，添加新的审批级别需要修改现有代码
- 代码可读性差，维护困难

### 职责链模式重构代码

```java title='审批请求对象'
public class AuthInfo {
    private String userId;
    private String orderId;
    private String level;
    
    public AuthInfo(String userId, String orderId, String level) {
        this.userId = userId;
        this.orderId = orderId;
        this.level = level;
    }
    
    // getter 和 setter 方法
    public String getUserId() { return userId; }
    public void setUserId(String userId) { this.userId = userId; }
    
    public String getOrderId() { return orderId; }
    public void setOrderId(String orderId) { this.orderId = orderId; }
    
    public String getLevel() { return level; }
    public void setLevel(String level) { this.level = level; }
}
```

```java title='抽象审批链'
public abstract class AuthLink {
    protected String levelUserId; // 级别人员ID
    protected String levelUserName; // 级别人员姓名
    private AuthLink next; // 责任链
    
    public AuthLink(String levelUserId, String levelUserName) {
        this.levelUserId = levelUserId;
        this.levelUserName = levelUserName;
    }
    
    public AuthLink next() {
        return next;
    }
    
    public AuthLink appendNext(AuthLink next) {
        this.next = next;
        return this;
    }
    
    public abstract AuthInfo doAuth(String uId, String orderId, AuthInfo authInfo);
}
```

### 职责链模式重构代码

![](https://wkq-img.oss-cn-chengdu.aliyuncs.com/site/20250823213751.png)

##  框架中的过滤器、拦截器

职责链模式常用在框架的开发中，为框架提供扩展点，让框架使用者可以在不修改框架源码的情况下，基于扩展点添加新的功能，职责链模式最常用来开发框架的过滤器和拦截器。

### Servlet Filter
Servlet Filter 是 Java Servlet 规范中定义的组件，翻译成中文就是过滤器，它可以实现对 HTTP 请求的过滤功能，比如鉴权、限流、记录日志、验证参数等等。因为它是 Servlet 规范的一部分，

所以，只要是支持 Servlet 的 Web 容器（比如 Tomcat 、Jetty 等），都支持过滤器功能。
![](https://wkq-img.oss-cn-chengdu.aliyuncs.com/site/20250913190921.png)

在实际项目中，使用 Servlet Filter 如下， 添加一个过滤器，只需要定义一个 javax.servlet.Filter 接口的过滤器，并且将它配置在 web.xml 配置文件中。Web 容器启动的时候，会读取 web.xml 中的配置，
创建过滤器对象。当有请求到来的时候，会先经过过滤器，然后才由 Servlet 来处理。

```java
public class LogFilter implements Filter {
  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
    // 在创建Filter时自动调用，
    // 其中filterConfig包含这个Filter的配置参数，比如name之类的（从配置文件中读取的）
  }

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    System.out.println("拦截客户端发送来的请求.");
    chain.doFilter(request, response);
    System.out.println("拦截发送给客户端的响应.");
  }

  @Override
  public void destroy() {
    // 在销毁Filter时自动调用
  }
}

// 在web.xml配置文件中如下配置：
<filter>
  <filter-name>logFilter</filter-name>
  <filter-class>com.xzg.cd.LogFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>logFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
```
在刚刚的示例代码中，添加过滤器非常方便，不需要修改任何代码，定义一个实现 javax.servlet.Filter 的类，再改改配置就搞定了，完全符合开闭原则。

Servlet Filter 做的如此好的扩展性，利用的就是职责链模式。

职责链模式的实现包含处理器接口（IHandler ）或抽象类（Handler）,以及处理器链（HandlerChain）。对应 Servlet Filter ，javax.servlet.Filter 就是处理器接口，FilterChain 就是处理器链。

Servlet 只是一个规范，并不包含具体的实现，所以 Servlet 中的 FilterChain 只是一个接口定义。具体的实现类由遵从 Servlet 规范的 Web 容器来提供，比如 ApplicationFilterChain 类就是 Tomcat 提供的 FilterChain 的实现类，源码如下所示。

```java
public final class ApplicationFilterChain implements FilterChain {
  private int pos = 0; //当前执行到了哪个filter
  private int n; //filter的个数
  private ApplicationFilterConfig[] filters;
  private Servlet servlet;

  @Override
  public void doFilter(ServletRequest request, ServletResponse response) {
    if (pos < n) {
      ApplicationFilterConfig filterConfig = filters[pos++];
      Filter filter = filterConfig.getFilter();
      filter.doFilter(request, response, this);
    } else {
      // filter都处理完毕后，执行servlet
      servlet.service(request, response);
    }
  }

  public void addFilter(ApplicationFilterConfig filterConfig) {
    for (ApplicationFilterConfig filter:filters)
      if (filter==filterConfig)
         return;

    if (n == filters.length) {//扩容
      ApplicationFilterConfig[] newFilters = new ApplicationFilterConfig[n + INCREMENT];
      System.arraycopy(filters, 0, newFilters, 0, n);
      filters = newFilters;
    }
    filters[n++] = filterConfig;
  }
}
```
ApplicationFilterChain 类的 doFilter()  函数的代码实现比较有技巧，实际上是一个递归调用。可以用每个 Filter （比如 LogFilter)的 doFilter 的代码实现，直接替换 ApplicationFilterChain 的第 12 行代码。

```java
  @Override
  public void doFilter(ServletRequest request, ServletResponse response) {
    if (pos < n) {
      ApplicationFilterConfig filterConfig = filters[pos++];
      Filter filter = filterConfig.getFilter();
      //filter.doFilter(request, response, this);
      //把filter.doFilter的代码实现展开替换到这里
      System.out.println("拦截客户端发送来的请求.");
      chain.doFilter(request, response); // chain就是this
      System.out.println("拦截发送给客户端的响应.")
    } else {
      // filter都处理完毕后，执行servlet
      servlet.service(request, response);
    }
  }
```
这样实现是为了在一个 doFilter() 方法中，支持双向拦截，技能拦截客户端发送来的请求，也能拦截发送给客户端的响应。

### Spring Interceptor
Spring Interceptor 翻译成中文就是拦截器，和 Servlet 的不同之处在于，Servlet Filter 是 Servlet 规范的一部分，实现依赖于 Web 容器。Spring Interceptor 是 Spring MVC 框架的一部分，由 Spring MVC 框架来提供实现。客户端发送的请求，会先经过 Servlet Filter ，然后再经过 Spring Interceptor ，最后到达具体的业务代码中。
![](https://wkq-img.oss-cn-chengdu.aliyuncs.com/site/20250913211609.png)

下面是使用 Spring Interception 的一个代码示例，实现的功能和上面的 LogFilter 完全相同，只是实现方式上稍有区别。LogFilter 对请求和响应的拦截是在 doFilter() 一个函数中实现的，而 LogInterceptor 对请求的拦截在 preHandle() 中实现，对响应的拦截在 postHandler() 中实现。

```java
public class LogInterceptor implements HandlerInterceptor {

  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    System.out.println("拦截客户端发送来的请求.");
    return true; // 继续后续的处理
  }

  @Override
  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    System.out.println("拦截发送给客户端的响应.");
  }

  @Override
  public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    System.out.println("这里总是被执行.");
  }
}

//在Spring MVC配置文件中配置interceptors
<mvc:interceptors>
   <mvc:interceptor>
       <mvc:mapping path="/*"/>
       <bean class="com.xzg.cd.LogInterceptor" />
   </mvc:interceptor>
</mvc:interceptors>
```
Spring Interceptor 底层依然是基于职责链模式实现的。其中，HandlerExecutionChain 类是职责链模式中的处理器链。它的实现相较于 Tomcat 中的 ApplicationFilterChain 来说，逻辑更加清晰，不需要使用递归来实现，主要是因为它将请求和响应的拦截工作，拆分到了两个函数中实现。HandlerExecutionChain 的源码如下所示：

```java
public class HandlerExecutionChain {
 private final Object handler;
 private HandlerInterceptor[] interceptors;

 public void addInterceptor(HandlerInterceptor interceptor) {
  initInterceptorList().add(interceptor);
 }

 boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
  HandlerInterceptor[] interceptors = getInterceptors();
  if (!ObjectUtils.isEmpty(interceptors)) {
   for (int i = 0; i < interceptors.length; i++) {
    HandlerInterceptor interceptor = interceptors[i];
    if (!interceptor.preHandle(request, response, this.handler)) {
     triggerAfterCompletion(request, response, null);
     return false;
    }
   }
  }
  return true;
 }

 void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
  HandlerInterceptor[] interceptors = getInterceptors();
  if (!ObjectUtils.isEmpty(interceptors)) {
   for (int i = interceptors.length - 1; i >= 0; i--) {
    HandlerInterceptor interceptor = interceptors[i];
    interceptor.postHandle(request, response, this.handler, mv);
   }
  }
 }

 void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
   throws Exception {
  HandlerInterceptor[] interceptors = getInterceptors();
  if (!ObjectUtils.isEmpty(interceptors)) {
   for (int i = this.interceptorIndex; i >= 0; i--) {
    HandlerInterceptor interceptor = interceptors[i];
    try {
     interceptor.afterCompletion(request, response, this.handler, ex);
    } catch (Throwable ex2) {
     logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
    }
   }
  }
 }
}
```
在 Spring 框架中，DispatcherServlet 的 doDispatch() 方法来分发请求，它在真正的业务逻辑执行前后，执行 HandlerExecutionChain 的 applyPreHandler() 和 applyPostHandler() 函数，用来实现拦截的功能。



## 总结
职责链模式，可以让框架代码满足开闭原则。添加一个新的处理器，只需要修改客户端代码。

职责链模式常用在框架的开发中，为框架提供扩展点，让框架使用者可以在不修改框架源码的情况下，基于扩展点添加新的功能，比如常见的过滤器、拦截器功能。


Filter 可以拿到原始的 http 请求，但是拿不到请求的控制器和请求控制器中的方法的信息；Interceptor 可以拿到
### 优点
* 降低了对象之间的耦合度：降低了请求发送者和接收者的耦合度
* 增强了系统的可扩展性： 可以根据需要增加新的请求处理类，满足开闭原则
* 增强了给对象指派职责的灵活性：当工作流程发生变化，可以动态地改变链内的成员或者修改它们。
* 责任链简化了对象之间的连接：一个对象只需要保持一个指向其后继者的引用，不需要保持其它所有者的引用，这避免了众多的 if 或者 if...else 语句。
* 责任分担：每个类只需要处理自己该处理的工作，不能处理的传递给下一个对象完成，明确各类的责任范围，符合单一职责原则。
### 缺点
* 不能保证每个请求一定被处理。由于一个请求没有明确的接收者，所以不能保证它一定被处理，该请求可能一直传到链的末端都得不到处理。
* 对比较长的职责链，请求的处理可能涉及多个处理对象，系统性能受到一定的影响。
* 职责链建立的合理性要靠客户端来保证，增加了客户端的复杂性，可能会由于职责链的错误设置而导致系统出错。比如循环调用等。
### 使用场景
* 在运行时需要动态使用多个关联对象来处理同一次请求时。比如，请假流程、员工入职流程、编译打包发布上线流程、敏感词过滤等。
* 不想让使用者知道具体的处理逻辑时，比如，做权限校验的登录拦截器。
* 需要动态更换处理对象时。比如，工单处理系统、网关 API 过滤规则系统等。
* 职责链模式经常被用在框架开发中，用来实现框架的过滤器、拦截器功能，让框架的使用者在不修改源码的情况下，添加新的拦截器功能。
